//
//	File Name   :	Dx10Texture2D.cpp
//	Description :	Dx10Texture2D implementation file.
//	Author		:	William McVicar
//  Mail		:	mcvicar.william@gmail.com
//

//  Precompiled Header
#include "CommonDefines.h"
#ifdef DX10
//  Library Includes

//  Local Includes
#include "ProteinFramework.h"
#include "RendererData.h"
#include "IRenderer.h"
#include "TextureBase.h"

//  This includes
#include "Dx10Texture2D.h"

//	Macros
#ifndef max
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif

//  Static Variables

//  Static Function Prototypes

//  Implementation

namespace Protein
{

CTexture2D::CTexture2D( const TextureBase* _pBase )
{
	D3D10_TEXTURE2D_DESC desc;
	memset( &desc, 0, sizeof( desc ) );

	desc.ArraySize			= 1;
	desc.Format				= DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; //adjust this based on actual formats
	desc.Width				= _pBase->image().Width();
	desc.Height				= _pBase->image().Height();
	desc.SampleDesc.Count	= 1;
	desc.Usage				= D3D10_USAGE_DEFAULT;
	desc.BindFlags			= D3D10_BIND_SHADER_RESOURCE;

	u32 uiMips = ( _pBase->image().MipMapCount() > 0 ) ? _pBase->image().MipMapCount() : 1;
	desc.MipLevels			= uiMips;

	D3D10_SUBRESOURCE_DATA* pInitData = new D3D10_SUBRESOURCE_DATA[ uiMips * desc.ArraySize ];
	u32 uiNumBytes = 0;
	u32 uiRowBytes = 0;
	u32 uiNumRows  = 0;
	u32 uiIndex	   = 0;

	u8* pSrcBits = _pBase->image().Data();
	for( UINT j = 0; j < desc.ArraySize; j++ )
    {
        UINT w = desc.Width;
        UINT h = desc.Height;
        for( UINT i = 0; i < uiMips; i++ )
        {
			memset( &pInitData[ uiIndex ], 0, sizeof( D3D10_SUBRESOURCE_DATA ) );
			i32 numBlocksWide = 0;
			if( w > 0 )
				numBlocksWide = max( 1, w / 4 );
			int numBlocksHigh = 0;
			if( h > 0 )
				numBlocksHigh = max( 1, h / 4 );
			uiRowBytes = numBlocksWide * 16;
			uiNumRows = numBlocksHigh;

			pInitData[uiIndex].pSysMem = pSrcBits;
            pInitData[uiIndex].SysMemPitch = uiRowBytes;
            ++uiIndex;
    
            pSrcBits += uiNumBytes;
            w = w >> 1;
            h = h >> 1;
            if( w == 0 )
                w = 1;
            if( h == 0 )
                h = 1;
        }
    }

	ID3D10Texture2D* pTex = NULL;
	HRESULT hr = renderer().GetRendererData()->m_pDevice->CreateTexture2D( &desc, pInitData, &pTex );
	PROTEIN_UNUSED( hr );

	D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
	memset( &srvDesc, 0, sizeof( srvDesc ) );
	srvDesc.Format = desc.Format;
	srvDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
	srvDesc.Texture2D.MipLevels = desc.MipLevels;
	hr = renderer().GetRendererData()->m_pDevice->CreateShaderResourceView( pTex, &srvDesc, &m_pSRV );
	PROTEIN_UNUSED( hr );
	pTex->Release();
	pTex = NULL;

	delete [] pInitData;
	pInitData = NULL;
}

CTexture2D::~CTexture2D()
{
	m_pSRV->Release();
	m_pSRV = NULL;
}

bool CTexture2D::Enable()
{
	renderer().GetRendererData()->m_pDevice->PSSetShaderResources( 0, 1, &m_pSRV );
	return true;
}

bool CTexture2D::Disable()
{
	return true;
}

}

#endif //DX10